﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using PloobsEngine.Material;

namespace PloobsEngine.SceneControl
{
    public class GBuffer : IDeferredGBuffer
    {

        private QuadRender quadRenderer;
        private EngineStuff engine;
        private RenderTarget2D colorRT;    //this Render Target will hold color and Specular Intensity
        private RenderTarget2D normalRT; //this Render Target will hold normals and Specular Power
        private RenderTarget2D depthRT; //finally, this one will hold the depth
        private RenderTarget2D lightOclusionRT; //finally, this one will hold the depth
        private Effect clearBufferEffect;
        private DepthStencilBuffer depthStencil;
        IRenderHelper render;
        #region IDeferredGBuffer Members

        public void SetGBuffer()
        {

            EngineStuff.GraphicsDevice.SetRenderTarget(0, colorRT);
            EngineStuff.GraphicsDevice.SetRenderTarget(1, normalRT);
            EngineStuff.GraphicsDevice.SetRenderTarget(2, depthRT);
            EngineStuff.GraphicsDevice.SetRenderTarget(3, lightOclusionRT);
        }

        public void ResolveGBuffer()
        {
            EngineStuff.GraphicsDevice.SetRenderTarget(0, null);
            EngineStuff.GraphicsDevice.SetRenderTarget(1, null);
            EngineStuff.GraphicsDevice.SetRenderTarget(2, null);
            EngineStuff.GraphicsDevice.SetRenderTarget(3, null);
        }
             
        public void ClearGBuffer()
        {
            DepthStencilBuffer d = EngineStuff.GraphicsDevice.DepthStencilBuffer;
            EngineStuff.GraphicsDevice.DepthStencilBuffer = depthStencil;
            //clearBufferEffect.Parameters["backGround"].SetValue(new Color(0.5f, 0.5f, 0.5f).ToVector3());

            clearBufferEffect.Begin();
            clearBufferEffect.Techniques[0].Passes[0].Begin();            
            quadRenderer.Render(Vector2.One * -1, Vector2.One);
            clearBufferEffect.Techniques[0].Passes[0].End();
            clearBufferEffect.End();
        }

        public void LoadContent(EngineStuff engine, IRenderHelper render)
        {
            this.engine = engine;
            this.render = render;
            quadRenderer = new QuadRender(EngineStuff.GraphicsDevice);
         
            colorRT = EngineStuff.GetDefaultColorBuffer();
            normalRT = EngineStuff.GetDefaultColorBuffer();
            depthRT = EngineStuff.GetDefaultDepthBuffer();
            lightOclusionRT = EngineStuff.GetDefaultVector4Buffer();
            depthStencil = EngineStuff.GetDefaultDepthStencil();

            clearBufferEffect = EngineStuff.InternalContentManager.GetAsset<Effect>("ClearGBuffer");
            
        }

        public Microsoft.Xna.Framework.Graphics.Texture2D this[GBufferTypes type]
        {
            get {

                switch (type)
                {
                    case GBufferTypes.DEPH:
                        return depthRT.GetTexture();
                    case GBufferTypes.COLOR:
                        return colorRT.GetTexture();
                    case GBufferTypes.NORMAL:
                        return normalRT.GetTexture();
                    case GBufferTypes.Extra1:
                        return lightOclusionRT.GetTexture();                                            
                    default:
                        throw new Exception("This GBUFFER dont use this Buffer Type");                        
                }
            }
        }

        public void DrawScene(GameTime gameTime, IWorld world)
        {                        
            EngineStuff.GraphicsDevice.RenderState.CullMode = CullMode.CullCounterClockwiseFace;
            engine.PreRender(gameTime,world.ActiveCamera.View,world.ActiveCamera.Projection);
            EngineStuff.GraphicsDevice.RenderState.AlphaBlendEnable = false;
            EngineStuff.GraphicsDevice.RenderState.DepthBufferEnable = true;
            EngineStuff.GraphicsDevice.RenderState.DepthBufferWriteEnable = true;
            foreach (IObject item in world.Culler.GetNotCulledObjectsList(world,world.ActiveCamera, MaterialType.DEFERRED))
            {
                item.Drawn(gameTime, world.ActiveCamera, world.Lights, render);
            }           
         
        }

        #endregion



        #region IDeferredGBuffer Members


        public void PreDrawScene(GameTime gameTime, IWorld world)
        {
            foreach (IObject item in world.Culler.GetNotCulledObjectsList(world,world.ActiveCamera, MaterialType.DEFERRED))
            {
                item.PreDrawn(world, gameTime, world.ActiveCamera, world.Lights, render);
            }
        }

        #endregion
    }
}
